<?php

declare (strict_types=1);
/**
 * @copyright 深圳市易果网络科技有限公司
 * @version 1.0.0
 * @link https://dayiguo.com
 */

namespace App\Service\User;

use App\Dao\BusinessDao;
use App\Dao\BusinessIndustryDao;
use App\Dao\CouponDao;
use App\Dao\LocationDao;
use App\Dao\UserBusinessFavDao;
use App\Exception\CustomException;
use App\Kernel\Util\UserJwtInstance;
use App\Service\Service;

use Hyperf\Di\Annotation\Inject;

/**
 * 商家服务
 *
 * @author 刘兴永(aile8880@qq.com)
 * @package App\Service\Admin
 */
class BusinessService extends Service
{
    /**
     * @Inject
     * @var BusinessDao
     */
    public $dao;

    /**
     * @Inject
     * @var CouponDao
     */
    public $coupon_dao;

    /**
     * @Inject
     * @var UserBusinessFavDao
     */
    public $user_business_dao;

    /**
     * @Inject
     * @var UserBusinessFavDao
     */
    public $user_business_fav;

    /**
     * @Inject
     * @var BusinessIndustryDao
     */
    public $business_industry_dao;


    /**
     * 地区Dao
     * @Inject()
     * @var LocationDao
     */
    public $location_dao;

    /**
     * 省市区ID数组
     * @param int $district_id
     * @return array
     */
    public function locationsArray(int $district_id)
    {
        $location_ids = [];
        if ($district_id > 0) {

            $district = $this->location_dao->getLocationByPid(['pid' => $district_id]);
            if ($district) {
                $location_ids[] = $district['pid']; // 区

                $city = $this->location_dao->getLocationByPid(['pid' => $district['level']]);

                if ($city) {
                    $location_ids[] = $city['pid']; // 市

                    $province = $this->location_dao->getLocationByPid(['pid' => $city['level']]);
                    $province && $location_ids[] = $province['pid'];

                }

            }
        }
        return $location_ids;
    }



    /**
     * 首页金刚区
     * @param int $industry_id
     * @param float $longitude
     * @param float $latitude
     * @param int $page
     * @param int $distance
     * @param int $type
     * @param $sort_type
     * @return mixed
     */
    public function iconNewPage(int $industry_id, float $longitude, float $latitude, int $page, int $distance, int $type, int $sort_type)
    {

        $coupon = $this->coupon_dao->get();

        $coupon_id = [];
        foreach ($coupon as $key => $value) {
            $coupon_id[] = $value['business_id'];
        }

        $business = $this->dao->getBusinessList([
            'industry_id' => $industry_id,
            'id' => ['in', $coupon_id]
        ]);

        $ids = [];
        foreach ( $business as $key => $value ) {
            $ids[] = $value['id'];
        }

        $ids = !empty($ids) ? $ids: $this->error();

        $strom = $this->getGeoCalculatorIconNewPage(0, $longitude, $latitude, $industry_id, $ids, $distance, $type, $sort_type , $page);

        return $strom;
    }

    /**
     * 以用户为中心，计算用户在某城市范围内附近的商家列表
     * 此方法带有缓存机制，在注入了UserMiddleware中间件的控制器调用此方法则会自动缓存结果
     * 否则每次都会实时调用
     *
     * @param int $city_id 城市ID，0代表不筛选城市
     * @param float $longitude 经度
     * @param float $latitude 纬度
     * @param int $industry_id 分类ID
     * @param array $businessIds 商家id
     * @param int $page 分页
     * @param int $distance
     * @param int $type
     * @param $sort_type
     * @return mixed
     */
    public function getGeoCalculatorIconNewPage(int $city_id, float $longitude, float $latitude, int $industry_id, array $businessIds, int $distance, int $type, int $sort_type,int $page = 1)
    {
        // 使用try接管中间件异常，可以根据用户登录情况做出灵活的缓存策略
//        try {
//            $user_id = uid();
//
//            // 从缓存中返回
//            $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id. ':industry'. $industry_id. ':paging'. $page;
//            $result = $this->redis->get($nearbyBusinessRedisKey);
//            if ($result) {
//                var_dump('我是从缓存中读取的');
//                return json_decode($result, true);
//            }
//        }
//        catch (CustomException $e) {}

        // 用户未登录或者缓存不存在。实时计算

        $map = [];
        !empty($businessIds) && $map['id'] = ['in', $businessIds];
        $city_id > 0 && $map['city_id'] = $city_id;

        switch ($type) {
            case 1: //优惠券
                $map['enable_coupon'] = 1;
                break;
            case 2: //现金抵用券
                $map['enable_voucher'] = 1;
                break;
            case 3: // 全店入住
                $map['enable_full_discount'] = 1;
                break;
        }

        $sort = "";
        switch ($sort_type) {
            case 1:
                $sort = "";
                break;
            case 2:
                $sort = "created_at desc";
                break;
        }

        // 获取商家列表
        $business_list = $this->dao->getBusinessListIcon($sort, $map );

        if (count($business_list) === 0) $this->error();

        // 数据导入redis
        $redis_key = 'geoBusiness:' . $longitude . ',' . $latitude;
        $this->redis->del($redis_key);
        foreach ($business_list as $key => $business) {
            $this->redis->rawCommand('geoadd', $redis_key, $business->longitude, $business->latitude, $business->id);
        }
        $result_list = [];
        // 获取2000公里中心范围内的数据
        // 并将redis计算结果并入原有的结果集
        // 将距离结果以友好的方式记录并展示
        $geo_result = $this->redis->rawCommand('georadius', $redis_key, $longitude, $latitude, '2000000', 'm', 'WITHDIST');
        foreach ($geo_result as $geo) {
            foreach ($business_list as $key => $business) {
                if ($geo[0] != $business->id) continue;
                $result_list[$key]['id'] = $business->id;
                $result_list[$key]['name'] = $business->name;
                $result_list[$key]['logo'] = $business->logo;
                $result_list[$key]['tag'] = $business->tag;
                $result_list[$key]['province'] = $business->province;
                $result_list[$key]['district'] = $business->district;
                $result_list[$key]['address'] = $business->address;
                $result_list[$key]['longitude'] = $business->longitude;
                $result_list[$key]['latitude'] = $business->latitude;
                $result_list[$key]['tel'] = $business->tel;
                $result_list[$key]['full_discount_rate'] = $business->full_discount_rate;
                $result_list[$key]['enable_full_discount'] = $business->enable_full_discount;
                $result_list[$key]['enable_voucher'] = $business->enable_voucher;
                $result_list[$key]['enable_coupon'] = $business->enable_coupon;
                $result_list[$key]['distance'] = $geo[1];
                $result_list[$key]['distance_desc'] = $geo[1] >= 1000 ? floor(($geo[1] / 1000) * 10) / 10 . 'km' : (int)$geo[1] . 'm';

            }
        }

        if( $distance == 1 ) {
            $cmf_arr = array_column($result_list, 'distance');
            array_multisort($cmf_arr, SORT_ASC , $result_list);
        }

        if( $distance == 2 ) {
            $cmf_arr = array_column($result_list, 'distance');
            array_multisort($cmf_arr, SORT_DESC , $result_list);
        }

        foreach ($result_list as $key => $value) {

            if( $value['enable_coupon'] == '1' ) {
                $result_list[$key]['coupon'] = $this->coupon_dao->getMainList(1,[
                    'business_id' => $value['id']
                ], 'created_at desc');
            }

            if( $value['enable_voucher'] == '1' ) {
                $result_list[$key]['coupon'] = $this->coupon_dao->getMainList(2,[
                    'business_id' => $value['id']
                ], 'created_at desc');
            }

            if( $value['enable_full_discount'] == '1' ) {
                $result_list[$key]['coupon'] = $this->coupon_dao->getMainList(3,[
                    'business_id' => $value['id']
                ], 'created_at desc');
            }
        }
        if (null !== $result_list) {
            try {
                $user_id = uid();

                // 将结果缓存起来，暂时设置缓存10分钟，后续考虑设置为更合理的数值
                $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id. ':industry'. $industry_id. ':paging'. $page;
                $this->redis->set($nearbyBusinessRedisKey, json_encode($result_list), 60 * 10);
            }
            catch (CustomException $e) {}
        }

        $start              = ($page - 1) * 10;//偏移量，当前页-1乘以每页显示条数
        $likeStores['data']         = array_slice($result_list, $start, 10);
        $likeStores['count']         = count($result_list);

        return !empty($likeStores) ? $likeStores: $this->error();
    }

    /**
     * 首页商家 - 新版本
     * @param float $longitude
     * @param float $latitude
     * @param int $page
     * @return mixed
     */
    public function homePage($longitude, $latitude,$page)
    {
        $coupon = $this->coupon_dao->get();

        $ids = [];
        foreach ($coupon as $key => $value) {
            $ids[] = $value['business_id'];
        }

        return $this->getGeoCalculatorNew(0,$longitude,$latitude,array_unique($ids),$page);
    }

    /**
     * 以用户为中心，计算用户在某城市范围内附近的商家列表
     * 此方法带有缓存机制，在注入了UserMiddleware中间件的控制器调用此方法则会自动缓存结果
     * 否则每次都会实时调用
     *
     * @param int $city_id 城市ID，0代表不筛选城市
     * @param s $longitude 经度
     * @param float $latitude 纬度
     * @param array $businessIds 商家id
     * @param int $paging
     * @return mixed
     */
    public function getGeoCalculatorNew(int $city_id, float $longitude, float $latitude,  array $businessIds = [], int $paging = 1)
    {
        // 使用try接管中间件异常，可以根据用户登录情况做出灵活的缓存策略
//        try {
//            $user_id = uid();
//
//            // 从缓存中返回
//            $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id. ':paging' . $paging;
//            $result = $this->redis->get($nearbyBusinessRedisKey);
//            if ($result) {
//                var_dump('我是从缓存中读取的');
//                return json_decode($result, true);
//            }
//        }
//        catch (CustomException $e) {}

        // 用户未登录或者缓存不存在。实时计算

        $map = [];
        !empty($businessIds) && $map['id'] = ['in', $businessIds];
        $city_id > 0 && $map['city_id'] = $city_id;


        // 获取商家列表
        $business_list = $this->dao->getBusinessList($map);

        if (count($business_list) === 0) $this->error();

        // 数据导入redis
        $redis_key = 'geoBusiness:' . $longitude . ',' . $latitude;
        $this->redis->del($redis_key);
        foreach ($business_list as $key => $business) {
            $this->redis->rawCommand('geoadd', $redis_key, $business->longitude, $business->latitude, $business->id);
        }
        $result_list = [];
        // 获取2000公里中心范围内的数据
        // 并将redis计算结果并入原有的结果集
        // 将距离结果以友好的方式记录并展示
        $geo_result = $this->redis->rawCommand('georadius', $redis_key, $longitude, $latitude, '2000000', 'm', 'WITHDIST');
        foreach ($geo_result as $geo) {
            foreach ($business_list as $key => $business) {
                if ($geo[0] != $business->id) continue;
                $result_list[$key]['id'] = $business->id;
                $result_list[$key]['name'] = $business->name;
                $result_list[$key]['logo'] = $business->logo;
                $result_list[$key]['tag'] = $business->tag;
                $result_list[$key]['province'] = $business->province;
                $result_list[$key]['district'] = $business->district;
                $result_list[$key]['address'] = $business->address;
                $result_list[$key]['longitude'] = $business->longitude;
                $result_list[$key]['latitude'] = $business->latitude;
                $result_list[$key]['tel'] = $business->tel;
                $result_list[$key]['full_discount_rate'] = $business->full_discount_rate;
                $result_list[$key]['enable_full_discount'] = $business->enable_full_discount;
                $result_list[$key]['enable_voucher'] = $business->enable_voucher;
                $result_list[$key]['enable_coupon'] = $business->enable_coupon;
                $result_list[$key]['distance'] = (int)$geo[1];
                $result_list[$key]['distance_desc'] = $geo[1] >= 1000 ? floor(($geo[1] / 1000) * 10) / 10 . 'km' : (int)$geo[1] . 'm';
            }
        }

        $cmf_arr = array_column($result_list, 'distance');
        array_multisort($cmf_arr, SORT_ASC, $result_list);

        foreach ($result_list as $key => $value) {

            if( $value['enable_coupon'] == '1' ) {
                $result_list[$key]['coupon'] = $this->coupon_dao->getMainList(1,[
                    'business_id' => $value['id']
                ], 'created_at desc');
            }

            if( $value['enable_voucher'] == '1' ) {
                $result_list[$key]['coupon'] = $this->coupon_dao->getMainList(2,[
                    'business_id' => $value['id']
                ], 'created_at desc');
            }

            if( $value['enable_full_discount'] == '1' ) {
                $result_list[$key]['coupon'] = $this->coupon_dao->getMainList(3,[
                    'business_id' => $value['id']
                ], 'created_at desc');
            }
        }

        if (null !== $result_list) {
            try {
                $user_id = uid();

                // 将结果缓存起来，暂时设置缓存10分钟，后续考虑设置为更合理的数值
                $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id. ':paging' . $paging;
                $this->redis->set($nearbyBusinessRedisKey, json_encode($result_list), 60 * 10);
            }
            catch (CustomException $e) {}
        }

        $start              = ($paging - 1) * 10;//偏移量，当前页-1乘以每页显示条数
        $likeStores['data']         = array_slice($result_list, $start, 10);
        $likeStores['count']         = count($result_list);

        return $likeStores;
    }

    /**
     * 首页搜索
     * @param string $content
     * @param float $longitude
     * @param float $latitude
     * @param int $distance
     * @param int $type
     * @param int $sort_type
     * @return mixed
     */
    public function search(string $content, float $longitude, float $latitude, int $page, int $distance, int $type, int $sort_type)
    {
        $coupon = $this->coupon_dao->get();

        $coupon_id = [];
        foreach ($coupon as $key => $value) {
            $coupon_id[] = $value['business_id'];
        }

        $business = $this->dao->getBusinessList([
            'name' => ['like', "%{$content}%"],
            'id' => ['in', $coupon_id]
        ]);

        $ids = [];
        foreach ( $business as $key => $value ) {
            $ids[] = $value['id'];
        }

        $ids = !empty($ids) ? $ids: $this->error();

        $strom = $this->geoCalculatorSearch(0, $longitude, $latitude, $ids, $page, $distance, $type, $sort_type );

        return $strom;
    }

    /**
     * 以用户为中心，计算用户在某城市范围内附近的商家列表
     * 此方法带有缓存机制，在注入了UserMiddleware中间件的控制器调用此方法则会自动缓存结果
     * 否则每次都会实时调用
     *
     * @param int $city_id 城市ID，0代表不筛选城市
     * @param s $longitude 经度
     * @param float $latitude 纬度
     * @param array $businessIds 商家id
     * @param int $paging
     * @param int $distance
     * @param int $type
     * @param int $sort_type
     * @return mixed
     */
    public function geoCalculatorSearch(int $city_id, float $longitude, float $latitude,  array $businessIds = [], int $paging = 1, int $distance, int $type, int $sort_type)
    {
        // 使用try接管中间件异常，可以根据用户登录情况做出灵活的缓存策略
//        try {
//            $user_id = uid();
//
//            // 从缓存中返回
//            $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id. ':paging' . $paging;
//            $result = $this->redis->get($nearbyBusinessRedisKey);
//            if ($result) {
//                var_dump('我是从缓存中读取的');
//                return json_decode($result, true);
//            }
//        }
//        catch (CustomException $e) {}

        // 用户未登录或者缓存不存在。实时计算

        $map = [];
        !empty($businessIds) && $map['id'] = ['in', $businessIds];
        $city_id > 0 && $map['city_id'] = $city_id;

        switch ($type) {
            case 1: //优惠券
                $map['enable_coupon'] = 1;
                break;
            case 2: //现金抵用券
                $map['enable_voucher'] = 1;
                break;
            case 3: // 全店入住
                $map['enable_full_discount'] = 1;
                break;
        }

        $sort = "";
        switch ($sort_type) {
            case 1:
                $sort = "";
                break;
            case 2:
                $sort = "created_at desc";
                break;
        }


        // 获取商家列表
        $business_list = $this->dao->getBusinessList($map);

        if (count($business_list) === 0) return $business_list;

        // 数据导入redis
        $redis_key = 'geoBusiness:' . $longitude . ',' . $latitude;
        $this->redis->del($redis_key);
        foreach ($business_list as $key => $business) {
            $this->redis->rawCommand('geoadd', $redis_key, $business->longitude, $business->latitude, $business->id);
        }
        $result_list = [];
        // 获取2000公里中心范围内的数据
        // 并将redis计算结果并入原有的结果集
        // 将距离结果以友好的方式记录并展示
        $geo_result = $this->redis->rawCommand('georadius', $redis_key, $longitude, $latitude, '2000000', 'm', 'WITHDIST');
        foreach ($geo_result as $geo) {
            foreach ($business_list as $key => $business) {
                if ($geo[0] != $business->id) continue;
                $result_list[$key]['id'] = $business->id;
                $result_list[$key]['name'] = $business->name;
                $result_list[$key]['logo'] = $business->logo;
                $result_list[$key]['tag'] = $business->tag;
                $result_list[$key]['province'] = $business->province;
                $result_list[$key]['district'] = $business->district;
                $result_list[$key]['address'] = $business->address;
                $result_list[$key]['longitude'] = $business->longitude;
                $result_list[$key]['latitude'] = $business->latitude;
                $result_list[$key]['tel'] = $business->tel;
                $result_list[$key]['full_discount_rate'] = $business->full_discount_rate;
                $result_list[$key]['enable_full_discount'] = $business->enable_full_discount;
                $result_list[$key]['enable_voucher'] = $business->enable_voucher;
                $result_list[$key]['enable_coupon'] = $business->enable_coupon;
                $result_list[$key]['distance'] = $geo[1];
                $result_list[$key]['distance_desc'] = $geo[1] >= 1000 ? floor(($geo[1] / 1000) * 10) / 10 . 'km' : (int)$geo[1] . 'm';

            }
        }

        if( $distance == 1 ) {
            $cmf_arr = array_column($result_list, 'distance');
            array_multisort($cmf_arr, SORT_ASC , $result_list);
        }

        if( $distance == 2 ) {
            $cmf_arr = array_column($result_list, 'distance');
            array_multisort($cmf_arr, SORT_DESC , $result_list);
        }

        foreach ($result_list as $key => $value) {

            if( $value['enable_coupon'] == '1' ) {
                $result_list[$key]['coupon'] = $this->coupon_dao->getMainList(1,[
                    'business_id' => $value['id']
                ], 'created_at desc');
            }

            if( $value['enable_voucher'] == '1' ) {
                $result_list[$key]['coupon'] = $this->coupon_dao->getMainList(2,[
                    'business_id' => $value['id']
                ], 'created_at desc');
            }

            if( $value['enable_full_discount'] == '1' ) {
                $result_list[$key]['coupon'] = $this->coupon_dao->getMainList(3,[
                    'business_id' => $value['id']
                ], 'created_at desc');
            }
        }

        if (null !== $result_list) {
            try {
                $user_id = uid();

                // 将结果缓存起来，暂时设置缓存10分钟，后续考虑设置为更合理的数值
                $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id. ':paging' . $paging;
                $this->redis->set($nearbyBusinessRedisKey, json_encode($result_list), 60 * 10);
            }
            catch (CustomException $e) {}
        }

        $start              = ($paging - 1) * 10;//偏移量，当前页-1乘以每页显示条数
        $likeStores['data']         = array_slice($result_list, $start, 10);
        $likeStores['count']         = count($result_list);

        return $likeStores;
    }

    /**
     * 首页金刚区
     * @param int $industry_id
     * @param float $longitude
     * @param float $latitude
     * @param int $page
     * @return mixed
     */
    public function iconNew(int $industry_id, float $longitude, float $latitude, int $page)
    {

        $coupon = $this->coupon_dao->get();

        $coupon_id = [];
        foreach ($coupon as $key => $value) {
            $coupon_id[] = $value['business_id'];
        }

        $business = $this->dao->getBusinessList([
            'industry_id' => $industry_id,
            'id' => ['in', $coupon_id]
        ]);

        $ids = [];
        foreach ( $business as $key => $value ) {
            $ids[] = $value['id'];
        }

        $ids = !empty($ids) ? $ids: $this->error();

        $strom = $this->geoCalculatorIconNew(0, $longitude, $latitude, $industry_id, $ids, $page );

        return $strom;
    }

    /**
     * 首页金刚区
     * @param int $industry_id
     * @param float $longitude
     * @param float $latitude
     * @return mixed
     */
    public function icon(int $industry_id, float $longitude, float $latitude)
    {

        $coupon = $this->coupon_dao->get();

        $coupon_id = [];
        foreach ($coupon as $key => $value) {
            $coupon_id[] = $value['business_id'];
        }

        $business = $this->dao->getBusinessList([
            'industry_id' => $industry_id,
            'id' => ['in', $coupon_id]
        ]);

        $ids = [];
        foreach ( $business as $key => $value ) {
            $ids[] = $value['id'];
        }

        $ids = !empty($ids) ? $ids: $this->success();

        $strom = $this->geoCalculatorIcon(0, $longitude, $latitude, $industry_id, $ids );

        return $strom;
    }

    /**
     * 以用户为中心，计算用户在某城市范围内附近的商家列表
     * 此方法带有缓存机制，在注入了UserMiddleware中间件的控制器调用此方法则会自动缓存结果
     * 否则每次都会实时调用
     *
     * @param int $city_id 城市ID，0代表不筛选城市
     * @param s $longitude 经度
     * @param float $latitude 纬度
     * @param array $businessIds 商家id
     * @param int $paging
     * @return mixed
     */
    public function geoCalculatorNew(int $city_id, float $longitude, float $latitude,  array $businessIds = [], int $paging = 1)
    {
        // 使用try接管中间件异常，可以根据用户登录情况做出灵活的缓存策略
//        try {
//            $user_id = uid();
//
//            // 从缓存中返回
//            $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id. ':paging' . $paging;
//            $result = $this->redis->get($nearbyBusinessRedisKey);
//            if ($result) {
//                var_dump('我是从缓存中读取的');
//                return json_decode($result, true);
//            }
//        }
//        catch (CustomException $e) {}

        // 用户未登录或者缓存不存在。实时计算

        $map = [];
        !empty($businessIds) && $map['id'] = ['in', $businessIds];
        $city_id > 0 && $map['city_id'] = $city_id;


        // 获取商家列表
        $business_list = $this->dao->getBusinessList($map);

        if (count($business_list) === 0) return $business_list;

        // 数据导入redis
        $redis_key = 'geoBusiness:' . $longitude . ',' . $latitude;
        $this->redis->del($redis_key);
        foreach ($business_list as $key => $business) {
            $this->redis->rawCommand('geoadd', $redis_key, $business->longitude, $business->latitude, $business->id);
        }
        $result_list = [];
        // 获取2000公里中心范围内的数据
        // 并将redis计算结果并入原有的结果集
        // 将距离结果以友好的方式记录并展示
        $geo_result = $this->redis->rawCommand('georadius', $redis_key, $longitude, $latitude, '2000000', 'm', 'WITHDIST');
        foreach ($geo_result as $geo) {
            foreach ($business_list as $key => $business) {
                if ($geo[0] != $business->id) continue;
                $result_list[$key]['distance'] = $geo[1];
                $result_list[$key]['distance_desc'] = $geo[1] >= 1000 ? floor(($geo[1] / 1000) * 10) / 10 . 'km' : (int)$geo[1] . 'm';
                $result_list[$key]['business_id'] = $business->id;

            }
        }

        $cmf_arr = array_column($result_list, 'distance');
        array_multisort($cmf_arr, SORT_ASC, $result_list);

        $ids = [];
        foreach ($result_list as $key => $value) {
            $ids[] = $value['business_id'];
        }

        $business_list_paging = $this->dao->getBusinessListPaging([
            'id' => ['in', $ids]
        ]);

        foreach ($business_list_paging as $key => $value) {
            foreach ($result_list as $k => $val) {
                if( $val['business_id'] == $value['id'] ) {
                    $business_list_paging[$key]['distance'] = $val['distance'];
                    $business_list_paging[$key]['distance_desc'] = $val['distance_desc'];
                }
            }

            if( $value['enable_coupon'] == '1' ) {
                $business_list_paging[$key]['coupon'] = $this->coupon_dao->getMainList(1,[
                    'business_id' => $value['id']
                ], 'created_at desc');
            }

            if( $value['enable_voucher'] == '1' ) {
                $business_list_paging[$key]['coupon'] = $this->coupon_dao->getMainList(2,[
                    'business_id' => $value['id']
                ], 'created_at desc');
            }

            if( $value['enable_full_discount'] == '1' ) {
                $business_list_paging[$key]['coupon'] = $this->coupon_dao->getMainList(3,[
                    'business_id' => $value['id']
                ], 'created_at desc');
            }
        }

        if (null !== $ids) {
            try {
                $user_id = uid();

                // 将结果缓存起来，暂时设置缓存10分钟，后续考虑设置为更合理的数值
                $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id. ':paging' . $paging;
                $this->redis->set($nearbyBusinessRedisKey, json_encode($business_list_paging->toArray()), 60 * 10);
            }
            catch (CustomException $e) {}
        }

        return $business_list_paging->toArray();
    }

    /**
     * 首页商家 - 新版本
     * @param float $longitude
     * @param float $latitude
     * @param int $page
     * @return mixed
     */
    public function index($longitude, $latitude,$page)
    {
        $coupon = $this->coupon_dao->get();

        $ids = [];
        foreach ($coupon as $key => $value) {
            $ids[] = $value['business_id'];
        }

        return $this->geoCalculatorNew(0,$longitude,$latitude,array_unique($ids),$page);
    }

    /**
     * 首页商家 - 老版本
     * @param float $longitude
     * @param float $latitude
     * @return mixed
     */
    public function main( $longitude, $latitude)
    {
        $coupon = $this->coupon_dao->get();

        $ids = [];
        foreach ($coupon as $key => $value) {
            $ids[] = $value['business_id'];
        }

        return $this->geoCalculator(0,$longitude,$latitude,array_unique($ids));
    }

    /**
     * 店铺详情
     *
     * @param int $business_id
     * @param float $longitude 经度
     * @param float $latitude 纬度
     * @return mixed
     */
    public function store( int $business_id, float $longitude,  float$latitude )
    {

        $data = $this->geoCalculatorOne(0, $longitude,$latitude, $business_id);

        $business_count = $this->user_business_dao->count([
            'business_id' => $business_id
        ]);

        $data['business_count'] = $business_count;

        $business_fav = $this->user_business_fav->first([
            'user_id' => uid(),
            'business_id' => $business_id
        ]);
        if( $business_fav ) {
            $data['business_fav'] = 1;
        } else {
            $data['business_fav'] = 0;
        }

        if( $data['enable_coupon'] == '1' ) {
            $data['coupon'] = $this->coupon_dao->getList(1,[
                'business_id' => $business_id
            ], 'created_at desc');
            if( $data ) {
                foreach ($data['coupon'] as $key => $value) {
                    $data['coupon'][$key]['rebate'] = filterMoney(($value['price'] / $value['goods_price'])*10,2);
                }
            }
        }

        if( $data['enable_voucher'] == '1' ) {
            $data['coupon'] = $this->coupon_dao->getList(2,[
                'business_id' => $business_id
            ], 'created_at desc');
            if( $data ) {
                foreach ($data['coupon'] as $key => $value) {
                    $data['coupon'][$key]['rebate'] = filterMoney(($value['price'] / $value['goods_price'])*10,2);
                }
            }
        }

        if( $data['enable_full_discount'] == '1' ) {
            $data['coupon'] = $this->coupon_dao->getList(3,[
                'business_id' => $business_id
            ], 'created_at desc');
        }

        return $data;
    }

    /**
     * 以用户为中心，计算用户在某城市范围内附近的商家列表
     * 此方法带有缓存机制，在注入了UserMiddleware中间件的控制器调用此方法则会自动缓存结果
     * 否则每次都会实时调用
     *
     * @param int $city_id 城市ID，0代表不筛选城市
     * @param float $longitude 经度
     * @param float $latitude 纬度
     * @param int $industry_id 分类ID
     * @param array $businessIds 商家id
     * @param int $page 分页
     * @return mixed
     */
    public function geoCalculatorIconNew(int $city_id, float $longitude, float $latitude, int $industry_id, array $businessIds,int $page)
    {
        // 使用try接管中间件异常，可以根据用户登录情况做出灵活的缓存策略
//        try {
//            $user_id = uid();
//
//            // 从缓存中返回
//            $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id. ':industry'. $industry_id. ':paging'. $page;
//            $result = $this->redis->get($nearbyBusinessRedisKey);
//            if ($result) {
//                var_dump('我是从缓存中读取的');
//                return json_decode($result, true);
//            }
//        }
//        catch (CustomException $e) {}

        // 用户未登录或者缓存不存在。实时计算

        $map = [];
        !empty($businessIds) && $map['id'] = ['in', $businessIds];
        $city_id > 0 && $map['city_id'] = $city_id;


        // 获取商家列表
        $business_list = $this->dao->getBusinessList($map);

        if (count($business_list) === 0) return $business_list;

        // 数据导入redis
        $redis_key = 'geoBusiness:' . $longitude . ',' . $latitude;
        $this->redis->del($redis_key);
        foreach ($business_list as $key => $business) {
            $this->redis->rawCommand('geoadd', $redis_key, $business->longitude, $business->latitude, $business->id);
        }

        // 获取2000公里中心范围内的数据
        // 并将redis计算结果并入原有的结果集
        // 将距离结果以友好的方式记录并展示
        $geo_result = $this->redis->rawCommand('georadius', $redis_key, $longitude, $latitude, '2000000', 'm', 'WITHDIST');
        foreach ($geo_result as $geo) {
            foreach ($business_list as $key => $business) {
                if ($geo[0] != $business->id) continue;
                $result_list[$key]['distance'] = $geo[1];
                $result_list[$key]['distance_desc'] = $geo[1] >= 1000 ? floor(($geo[1] / 1000) * 10) / 10 . 'km' : (int)$geo[1] . 'm';
                $result_list[$key]['business_id'] = $business->id;
            }
        }
        $cmf_arr = array_column($result_list, 'distance');

        array_multisort($cmf_arr, SORT_ASC, $result_list);
        $ids = [];
        foreach ($result_list as $key => $value) {
            $ids[] = $value['business_id'];
        }

        $business_list_paging = $this->dao->getBusinessListPaging([
            'id' =>  ['in',$ids]
        ]);

        foreach ($business_list_paging as $key => $value) {
            foreach ($result_list as $k => $val) {
                if( $val['business_id'] == $value['id'] ) {
                    $business_list_paging[$key]['distance'] = $val['distance'];
                    $business_list_paging[$key]['distance_desc'] = $val['distance_desc'];
                }
            }

            if( $value['enable_coupon'] == '1' ) {
                $business_list_paging[$key]['coupon'] = $this->coupon_dao->getMainList(1,[
                    'business_id' => $value['id']
                ], 'created_at desc');
            }

            if( $value['enable_voucher'] == '1' ) {
                $business_list_paging[$key]['coupon'] = $this->coupon_dao->getMainList(2,[
                    'business_id' => $value['id']
                ], 'created_at desc');
            }

            if( $value['enable_full_discount'] == '1' ) {
                $business_list_paging[$key]['coupon'] = $this->coupon_dao->getMainList(3,[
                    'business_id' => $value['id']
                ], 'created_at desc');
            }
        }
        if (null !== $businessIds) {
            try {
                $user_id = uid();

                // 将结果缓存起来，暂时设置缓存10分钟，后续考虑设置为更合理的数值
                $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id. ':industry'. $industry_id. ':paging'. $page;
                $this->redis->set($nearbyBusinessRedisKey, json_encode($business_list_paging), 60 * 10);
            }
            catch (CustomException $e) {}
        }

        return !empty($business_list_paging) ? $business_list_paging->toArray(): $this->error();
    }

    /**
     * 以用户为中心，计算用户在某城市范围内附近的商家列表
     * 此方法带有缓存机制，在注入了UserMiddleware中间件的控制器调用此方法则会自动缓存结果
     * 否则每次都会实时调用
     *
     * @param int $city_id 城市ID，0代表不筛选城市
     * @param float $longitude 经度
     * @param float $latitude 纬度
     * @param int $industry_id 分类ID
     * @param array $businessIds 商家id
     * @return mixed
     */
    public function geoCalculatorIcon(int $city_id, float $longitude, float $latitude, int $industry_id, array $businessIds)
    {
        // 使用try接管中间件异常，可以根据用户登录情况做出灵活的缓存策略
        try {
            $user_id = uid();

            // 从缓存中返回
            $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id. ':industry'. $industry_id;
            $result = $this->redis->get($nearbyBusinessRedisKey);
            if ($result) {
                var_dump('我是从缓存中读取的');
                return json_decode($result, true);
            }
        }
        catch (CustomException $e) {}

        // 用户未登录或者缓存不存在。实时计算

        $map = [];
        !empty($businessIds) && $map['id'] = ['in', $businessIds];
        $city_id > 0 && $map['city_id'] = $city_id;


        // 获取商家列表
        $business_list = $this->dao->getBusinessList($map);

        if (count($business_list) === 0) return $business_list;

        // 数据导入redis
        $redis_key = 'geoBusiness:' . $longitude . ',' . $latitude;
        $this->redis->del($redis_key);
        foreach ($business_list as $key => $business) {
            $this->redis->rawCommand('geoadd', $redis_key, $business->longitude, $business->latitude, $business->id);
        }

        // 获取2000公里中心范围内的数据
        // 并将redis计算结果并入原有的结果集
        // 将距离结果以友好的方式记录并展示
        $geo_result = $this->redis->rawCommand('georadius', $redis_key, $longitude, $latitude, '2000000', 'm', 'WITHDIST');
        foreach ($geo_result as $geo) {
            foreach ($business_list as $key => $business) {
                if ($geo[0] != $business->id) continue;
                $business_list[$key]['distance'] = $geo[1];
                $business_list[$key]['distance_desc'] = $geo[1] >= 1000 ? floor(($geo[1] / 1000) * 10) / 10 . 'km' : (int)$geo[1] . 'm';
                if( $business['enable_coupon'] == '1' ) {
                    $business_list[$key]['coupon'] = $this->coupon_dao->getList(1,[
                        'business_id' => $business->id
                    ], 'created_at desc');
                }

                if( $business['enable_voucher'] == '1' ) {
                    $business_list[$key]['coupon'] = $this->coupon_dao->getList(2,[
                        'business_id' => $business->id
                    ], 'created_at desc');
                }

                if( $business['enable_full_discount'] == '1' ) {
                    $business_list[$key]['coupon'] = $this->coupon_dao->getList(3,[
                        'business_id' => $business->id
                    ], 'created_at desc');
                }
            }
        }

        if (null !== $businessIds) {
            try {
                $user_id = uid();

                // 将结果缓存起来，暂时设置缓存10分钟，后续考虑设置为更合理的数值
                $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id. ':industry'. $industry_id;
                $this->redis->set($nearbyBusinessRedisKey, json_encode($business_list), 60 * 10);
            }
            catch (CustomException $e) {}
        }

        return $business_list->toArray();
    }

    /**
     * 以用户为中心，计算用户在某城市范围内附近的商家列表
     * 此方法带有缓存机制，在注入了UserMiddleware中间件的控制器调用此方法则会自动缓存结果
     * 否则每次都会实时调用
     *
     * @param int $city_id 城市ID，0代表不筛选城市
     * @param float $longitude 经度
     * @param float $latitude 纬度
     * @param array $businessIds 商家id
     * @return mixed
     */
    public function geoCalculator(int $city_id, float $longitude, float $latitude,  array $businessIds = [])
    {
        // 使用try接管中间件异常，可以根据用户登录情况做出灵活的缓存策略
//        try {
//            $user_id = uid();
//
//            // 从缓存中返回
//            $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id;
//            $result = $this->redis->get($nearbyBusinessRedisKey);
//            if ($result) {
//                var_dump('我是从缓存中读取的');
//                return json_decode($result, true);
//            }
//        }
//        catch (CustomException $e) {}

        // 用户未登录或者缓存不存在。实时计算

        $map = [];
        !empty($businessIds) && $map['id'] = ['in', $businessIds];
        $city_id > 0 && $map['city_id'] = $city_id;


        // 获取商家列表
        $business_list = $this->dao->getBusinessList($map);

        if (count($business_list) === 0) return $business_list;

        // 数据导入redis
        $redis_key = 'geoBusiness:' . $longitude . ',' . $latitude;
        $this->redis->del($redis_key);
        foreach ($business_list as $key => $business) {
            $this->redis->rawCommand('geoadd', $redis_key, $business->longitude, $business->latitude, $business->id);
        }

        // 获取2000公里中心范围内的数据
        // 并将redis计算结果并入原有的结果集
        // 将距离结果以友好的方式记录并展示
        $geo_result = $this->redis->rawCommand('georadius', $redis_key, $longitude, $latitude, '2000000', 'm', 'WITHDIST');
        foreach ($geo_result as $geo) {
            foreach ($business_list as $key => $business) {
                if ($geo[0] != $business->id) continue;
                $business_list[$key]['distance'] = $geo[1];
                $business_list[$key]['distance_desc'] = $geo[1] >= 1000 ? floor(($geo[1] / 1000) * 10) / 10 . 'km' : (int)$geo[1] . 'm';

                if( $business['enable_coupon'] == '1' ) {
                    $business_list[$key]['coupon'] = $this->coupon_dao->getList(1,[
                        'business_id' => $business->id
                    ], 'created_at desc');
                }

                if( $business['enable_voucher'] == '1' ) {
                    $business_list[$key]['coupon'] = $this->coupon_dao->getList(2,[
                        'business_id' => $business->id
                    ], 'created_at desc');
                }

                if( $business['enable_full_discount'] == '1' ) {
                    $business_list[$key]['coupon'] = $this->coupon_dao->getList(3,[
                        'business_id' => $business->id
                    ], 'created_at desc');
                }

            }
        }

        if (null !== $businessIds) {
            try {
                $user_id = uid();

                // 将结果缓存起来，暂时设置缓存10分钟，后续考虑设置为更合理的数值
                $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id;
                $this->redis->set($nearbyBusinessRedisKey, json_encode($business_list), 60 * 10);
            }
            catch (CustomException $e) {}
        }

        return $business_list->toArray();
    }

    /**
     * 通过店铺ID去查询数据
     *
     *
     *
     * @param int $city_id 城市ID，0代表不筛选城市
     * @param float $longitude 经度
     * @param float $latitude 纬度
     * @param int $businessIds 商家id
     * @return mixed
     */
    public function geoCalculatorOne(int $city_id, float $longitude, float $latitude, int $businessIds)
    {
        // 使用try接管中间件异常，可以根据用户登录情况做出灵活的缓存策略
        try {
            $user_id = uid();

            // 从缓存中返回
            $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id.':business_id'.$businessIds;
            $result = $this->redis->get($nearbyBusinessRedisKey);
            if ($result) {
                var_dump('我是从缓存中读取的');
                return json_decode($result, true);
            }
        }
        catch (CustomException $e) {}

        // 用户未登录或者缓存不存在。实时计算

        $map = [];
        !empty($businessIds) && $map['id'] = $businessIds;
        $city_id > 0 && $map['city_id'] = $city_id;

        // 获取商家列表
        $business_list = $this->dao->getBusinessFirst($map);

        // 数据导入redis
        $redis_key = 'geoBusiness:' . $longitude . ',' . $latitude;
        $this->redis->del($redis_key);

        $this->redis->rawCommand('geoadd', $redis_key, $business_list['longitude'], $business_list['latitude'], $business_list['id']);

        // 获取2000公里中心范围内的数据
        // 并将redis计算结果并入原有的结果集
        // 将距离结果以友好的方式记录并展示
        $geo_result = $this->redis->rawCommand('georadius', $redis_key, $longitude, $latitude, '2000000', 'm', 'WITHDIST');
        foreach ($geo_result as $geo) {
            if ($geo[0] != $business_list['id']) continue;
            $business_list['distance'] = $geo[1];
            $business_list['distance_desc'] = $geo[1] >= 1000 ? floor(($geo[1] / 1000) * 10) / 10 . 'km' : (int)$geo[1] . 'm';
        }

        if (null !== $businessIds) {
            try {
                $user_id = uid();

                // 将结果缓存起来，暂时设置缓存10分钟，后续考虑设置为更合理的数值
                $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id.':business_id'.$businessIds;
                $this->redis->set($nearbyBusinessRedisKey, json_encode($business_list), 60);
            }
            catch (CustomException $e) {}
        }

        return $business_list->toArray();
    }
}